package com.hup.minicontroller.server.service;

import android.os.Build;
import android.util.Log;

import com.hup.minicontroller.common.constant.BroadcastConstant;
import com.hup.minicontroller.common.framework.SubThreadHandler;
import com.hup.minicontroller.server.ServerApplication;
import com.hup.minicontroller.server.model.AppConfig;
import com.hup.minicontroller.server.model.AppState;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

/**
 * 局域网UPD广播发送端;<pre>
 * .实现发送UDP广播,使客户端发现服务端的功能;
 * .目前只支持正常路由器(非安卓热点,跨级路由)下的局域网广播收发功能
 *
 * 关于安卓UDP广播:
 * .广播收发功能能否正常使用的影响因素:安卓系统版本,品牌ROM,是否已开启[wifi/热点/移动网络],广播ip是否正确
 * .对于[wifi/热点/移动网络]的要求,貌似每个设备都不太一样(有的要联网才能调api,有的不用);所以本类操作MulticastSocket时,不管设备状态,每次操作一律都tryCatch
 * .某些文章说,某些ROM会阉割掉UDP广播(不是UDP通信)功能
 * 资料
 * https://blog.csdn.net/jyqqhw_41/article/details/49704167
 * https://www.cnblogs.com/zhongshiqiang/p/5899199.html
 * https://blog.csdn.net/u011418943/article/details/92839617
 *
 * @author hugan
 * @date 2021/5/10
 */
public class LanBroadcastSenderService {
    private static final String TAG = LanBroadcastSenderService.class.getSimpleName();

    private final SubThreadHandler handler;
    private Sender sender;
    private boolean isStart;

    public LanBroadcastSenderService() {
        handler = ServerApplication.getBean(SubThreadHandler.class);
        try {
            sender = new Sender();
        } catch (IOException e) {
            Log.e(TAG, "LanBroadcastSenderService: UDP广播初始化异常:", e);
        }
    }

    public void switchService(boolean isStart) {
        Log.i(TAG, "switchService: " + isStart);
        if (sender == null) return;
        this.isStart = isStart;
        if (isStart) {
            Log.i(TAG, "run: 开始发送广播");
            handler.post(sender);
        }
    }

    public void doTerminate() {
        if (sender != null) sender.doTerminate();
    }

    private class Sender implements Runnable {
        private final AppState appState;

        private final int broadcastPort;
        private final InetAddress broadcastAddress;
        private final MulticastSocket multicastSocketSender;

        public Sender() throws IOException {
            appState = ServerApplication.getBean(MainService.class).getAppState();
            AppConfig appConfig = appState.getAppConfig();
            broadcastPort = appConfig.getLanBroadcastPort();
            broadcastAddress = InetAddress.getByName(appConfig.getBroadcastIp());
            multicastSocketSender = new MulticastSocket();
        }

        @Override
        public void run() {
            if (!isStart || !appState.isStartedLan()) {
                Log.i(TAG, "run: 停止发送广播");
                isStart = false;
                return;
            }
            try {
                String msg = BroadcastConstant.MSG_HEAD + Build.MODEL;//设备名
                byte[] data = msg.getBytes();
                DatagramPacket packet = new DatagramPacket(data,
                        Math.min(data.length, BroadcastConstant.MAX_MSG_LENGTH),
                        broadcastAddress, broadcastPort);
                multicastSocketSender.send(packet);
                //Log.i(TAG, "run: 已发送:" + msg);
            } catch (Exception e) {
                Log.d(TAG, "广播发送错误: " + e);
            }
            if (!isStart) {
                Log.i(TAG, "run: 停止发送广播");
            } else {
                /*
                不管是否成功,只要isStart和isStartedLan,都会不断发送广播,
                因为可能是没开wifi/热点/移动网络造成消息发送失败
                 */
                handler.postDelayed(this, BroadcastConstant.SERVER_SEND_SPAN);
            }
        }

        public void doTerminate() {
            Log.i(TAG, "doTerminate: ");
            isStart = false;
            multicastSocketSender.close();
        }

    }

}
